package com.itheima.ioc.service.impl;

import com.itheima.ioc.dao.UserDao;
import com.itheima.ioc.dao.impl.UserDaoImpl;
import com.itheima.ioc.dao.impl.UserDaoImpl2;
import com.itheima.ioc.service.UserService;
import com.itheima.ioc.util.BeanFactory;
import org.junit.Test;

import java.util.ResourceBundle;
/*
    TODO: javaweb三层经典架构 (web,service,dao)
        web层调用service层,service层调用dao层

    TODO 当前案例,模拟的是service层调用dao层
        代码制作原则: 高内聚,低耦合
            (当需求改变的时候,代码改的越少,耦合度就越低)
        1. 主动创建对象
            1). 优点: 最简单
            2). 缺点: 耦合度高
                方案一切换成方案二, 左右两边的代码都修改了
        2. 面向接口编程(多态)
            公式: 接口类型 变量 = 接口实现类对象
            后续编写代码,只关注接口,不关注具体实现
            1). 优点: 相对于1, 耦合度降低
                 方案一切换成方案二, 只需要修改右边就可以了
            2). 缺点: 相对于3,耦合度还是高了一些
        3.  反射 + 配置文件
            1). 优点: 相对于2,耦合度更低了
                 方案一切换成方案二, 代码的右边也不需要修改了,只要修改配置文件即可
                 (修改代码需要重新编译,而配置文件不需要,修改配置文件比修改代码的代价低)
            2). 缺点: 相对于4,代码太多了
        4. 工厂模式
            1). 优点: 相对于3,代码更简洁了
            2). 工厂模式: 生产对象

     TODO   层层变化, 降低耦合, 提高代码复用性!!!

     IOC : inversion of control(控制反转)
     1. 控制: 对象的控制权(创建和管理)
     2. 反转: 对象的控制权从开发者手里转移到工厂的容器中
        开发者来说,以后需要某个对象,就需要先放到容器中,然后再从容器中获取

     3. 原理:
        1). 面向接口
        2). 反射+配置文件
        3). 工厂模式
     4. 实现
        1). 开发者在文件中配置: 工厂会加载配置文件,然后将对象放到容器中
        2). 开发者从工厂的容器中获取
 */
public class UserServiceImpl implements UserService {

    @Test
    @Override
    public void add() throws Exception {
        //1. 主动创建对象
//        UserDaoImpl userDao = new UserDaoImpl(); // 方案一
//        UserDaoImpl2 userDao = new UserDaoImpl2(); // 方案二
//        userDao.addUser();
        //2. 面向接口编程 : 解耦
//        UserDao userDao = new UserDaoImpl(); // 方案一
//        UserDao userDao = new UserDaoImpl2(); // 方案二
//        userDao.addUser();
        //3. 反射 + 配置文件 : 进一步解耦
//        ResourceBundle bundle = ResourceBundle.getBundle("data");
//        String userDaoClassName = bundle.getString("userDao");
//
//        Class<?> clazz = Class.forName(userDaoClassName);
//        UserDao userDao = (UserDao) clazz.newInstance();
//        userDao.addUser();

        //4. 工厂模式 : 统一管理bean的创建
        UserDao userDao = (UserDao) BeanFactory.getBean("userDao");
        userDao.addUser();
    }
}
